package com.dave.weixin.common.nio.channel;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

/**
 * Created by Dave on 2018/7/12
 * Describes Socket通道
 */
public class SocketChannelTest {


    ///////////////////////////////////////////////////////////////////////////
    // SocketChannel是一个连接到TCP网络套接字的通道
    // 2种方式创建SocketChannel：
    // ①打开一个SocketChannel并连接到互联网上的某台服务器。
    // ②一个新连接到达ServerSocketChannel时，会创建一个SocketChannel。
    ///////////////////////////////////////////////////////////////////////////
    public static void main(String[] args) {

    }

    /**
     * 创建和读写
     *
     * @throws IOException
     */
    private static void createSocketChannel() throws IOException {

        //创建
        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.connect(new InetSocketAddress("www.baidu.com", 80));

        //读取数据
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        //返回读取了多少个字节 文未标志为-1
        int read = socketChannel.read(buffer);

        //写入数据
        String writeData = "hello world!";
        ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
        writeBuffer.clear();
        writeBuffer.put(writeData.getBytes());
        //切换为读模式
        writeBuffer.flip();
        //Write()方法无法保证能写多少字节到SocketChannel。所以，我们重复调用write()直到Buffer没有要写的字节为止
        while (writeBuffer.hasRemaining()) {
            socketChannel.write(buffer);
        }

        //关闭
        socketChannel.close();
    }

    /**
     * 非阻塞模式通道
     */
    private static void nonBlockingSocketChannel() throws IOException {

        SocketChannel socketChannel = SocketChannel.open();
        //切换为非阻塞模式
        socketChannel.configureBlocking(false);

        //如果SocketChannel在非阻塞模式下，此时调用connect()，该方法可能在连接建立之前就返回了
        socketChannel.connect(new InetSocketAddress("www.baidu.com", 8080));

        //为了确定连接是否建立，可以调用finishConnect()的方法
        while (!socketChannel.finishConnect()) {
            System.out.println("等待socket创建。。干点其他事吧。。。");
        }

        ByteBuffer buffer = ByteBuffer.allocate(1024);

        //非阻塞模式下,read()方法在尚未读取到任何数据时可能就返回了。所以需要关注它的int返回
        int read = socketChannel.read(buffer);
        while (read != -1) {
            read = socketChannel.read(buffer);
        }

        buffer.clear();
        buffer.put("hello wang ba dan".getBytes());
        buffer.flip();
        //非阻塞模式下，write()方法在尚未写出任何内容时可能就返回了。所以需要在循环中调用write()。
        while (buffer.hasRemaining()) {
            socketChannel.write(buffer);
        }


    }


}
